package com.huajx.core.handler;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.huajx.core.Hboot;
import com.huajx.core.web.HbootWebConfig;
import com.huajx.util.StrUtil;
import com.huajx.util.collection.CollUtil;
import com.huajx.util.io.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.huajx.core.exception.RouteNotFoundException;
import com.huajx.core.model.HttpRequestMessage;
import com.huajx.core.model.HttpResponseMessage;

public class RouteHandler implements HttpHandler {
    private final static Map<String, Invoke> routes = new ConcurrentHashMap<>();
    private final static Logger logger = LoggerFactory.getLogger(RouteHandler.class);

    private static String template = Hboot.config(HbootWebConfig.class).getTemplate();//ConfigKit.getStr("config.template", "/page");

    public static void add(String controllerKey, Class<? extends Controller> clazz) {
        Method[] methods = clazz.getDeclaredMethods(); // 获取实体类的所有方法，返回Method数组

        for (int j = 0; j < methods.length; j++) { // 遍历所有方法
            Invoke invoke = new Invoke();
            invoke.setController(clazz);
            invoke.setControllerKey(controllerKey);
            Method method = methods[j];
            invoke.setMethod(method);
            String methodName = method.getName();
            invoke.setMethodName(methodName);

            if (StrUtil.equals(methodName, "index")) {
                routes.put(controllerKey, invoke);
            }

            String ck = controllerKey.endsWith("/") ? controllerKey + methodName : controllerKey + "/" + methodName;

            invoke.setViewPath(ck + ".html");

            routes.put(ck, invoke);

            logger.debug(routes.toString());
        }
    }

    public static void add(String controllerKey, Class<? extends Controller> clazz, String viewPath) {
        Method[] methods = clazz.getDeclaredMethods(); // 获取实体类的所有方法，返回Method数组

        for (int j = 0; j < methods.length; j++) { // 遍历所有方法
            Invoke invoke = new Invoke();
            invoke.setController(clazz);
            Method method = methods[j];
            invoke.setMethod(method);
            invoke.setControllerKey(controllerKey);

            String methodName = method.getName();
            invoke.setMethodName(methodName);
            if (StrUtil.equals(methodName, "index")) {
                routes.put(controllerKey, invoke);
            }

            String ck = controllerKey + "/" + methodName;

            viewPath = viewPath + "/" + methodName;

            invoke.setViewPath(viewPath + ".html");
            routes.put(ck, invoke);
        }
        // Invoke invoke = new Invoke();
        // invoke.setController(clazz);
        //
        // invoke.setControllerKey(controllerKey);
        //
        // invoke.setViewPath( viewPath );
        //
        // routes.put(controllerKey, invoke);
    }

    @Override
    public HttpResponseMessage handle(HttpRequestMessage request) {
        String context = request.getContext();
        HttpResponseMessage response = new HttpResponseMessage();
        response.setResponseCode(HttpResponseMessage.HTTP_STATUS_SUCCESS);

        if (request.getMethod().equals("OPTIONS")) {
            return response;
        }

        String contentType = ConstantHttp.get(context);
        if (StrUtil.isBlank(contentType)) {
            Invoke invoke = getInvoke(context);
            if (invoke != null) {
                invoke.setRequest(request);
                try {
                    invoke.setResponse(response);
                    invoke.invoke();
                } catch (InvocationTargetException | IllegalAccessException | InstantiationException e) {
                    e.printStackTrace();
                }
            }
        } else { // 处理所有静态文件
            try {
                response.setContentType(contentType);
                File file = FileUtil.file(StrUtil.join(true, "/", template, context));
                byte[] content = new byte[0];
                if (file.exists()) {
                    content = FileUtil.readBytes(file);
                } else {
                    if(context.startsWith("/")){
                        context = context.substring(1);
                    }
                    file = FileUtil.file(context);
                    if (file.exists()) {
                        content = FileUtil.readBytes(file);
                    }
                }
                logger.info(file.getAbsolutePath());
//                byte[] content = FileUtil.readBytes();
                response.appendBody(content);
//				FileUtil.writeToStream(response);
//				response.appendBody(FileKit.loadFile(StrUtil.appendSuffix(template, context, "/")));//"/page/" + context));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return response;
    }

    public static Invoke getInvoke(String cxt) {
        if (cxt == null) {
            throw new RouteNotFoundException("请求路径为空");
        }

        if(StrUtil.isBlank(cxt) || cxt.equals("/") || cxt.equals("//")){
            Invoke invoke = routes.get("/");
            return invoke;
        }else{
            cxt = cxt.startsWith("/") ? cxt : "/" + cxt;
            cxt = cxt.replace("//", "/");
            if (cxt.contains("?")) {
                cxt = cxt.substring(0, cxt.indexOf("?"));
            }

            if (cxt.endsWith("/")) {
                cxt = cxt.substring(0, cxt.indexOf("/"));
            }
        }

//		cxt = cxt.substring(0, cxt.indexOf("#"));

        Invoke invoke = routes.get(cxt);
        if (invoke == null) {
            cxt = StrUtil.subBefore(cxt, '/', true);
            if (StrUtil.isBlank(cxt) || cxt.equals("/")) {
                throw new RouteNotFoundException(cxt);
            } else {
                invoke = getInvoke(cxt);
            }
        }
        return invoke;
    }
}
